﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Sinacor.OMM.HFTMessageManager.ProcessEntity.Parameter;
using Sinacor.OMM.Configuration.HFTMessageManager;
using Sinacor.OMM.ConnectionManager.MSMQ;
using Sinacor.OMM.Logging;
using Sinacor.OMM.HFTMessageManager.ProcessEntity;
using Sinacor.OMM.HealthMonitor.Collector;
using Sinacor.OMM.HealthMonitor.Collector.SharedHealthDataMemoryStorage.HftProcessor;
using System.Diagnostics;
using Sinacor.OMM.ConnectionManager.DataBase;
using Sinacor.OMM.MessageEntity;
using Sinacor.OMM.Util;
using Sinacor.OMM.Configuration.Router;
using System.Net;
using PSE.Framework.Threading;

namespace Sinacor.OMM.HFTMessageManager.ProcessLogic
{
    public class STMMessageFlow : IDisposable
    {
        #region Propriedades
        private Sinacor.OMM.ConnectionManager.DataBase.DataBaseCommunicator dataBaseComunicator;
        private Translator.Interfaces.ITranslator _translator;
        private DateTime _OrderDate;
        private MsmqReceiver _msmqReceiver;
        private OMM.HFTMessageManager.ResourceAccess.HFTMessage _raHFTMessage;
        private bool running;

        private int _totalMessageSentPerInterval = 0;
        private int _totalDBPerInterval = 0;
        private long _TotalMessagesProcessed = 0;
        private long _TotalWaitOpenOrderTime = 0;
        private const int _waitTime = 60000;
        private DateTime _lastHealthStatusChecked = DateTime.Now;
        private DateTime _lastHealthDBStatusChecked = DateTime.Now;
        private DateTime _lastProcessTime = DateTime.Now;
        private DateTime _currentDate;
        private HealthMonitorCollector _healthMonitor;
        private HFTLastIdFileManager _hftLastIdFileManager;
        private HftProcessorShdms _hftProcessorStatus;
        private TraceWriter _traceWriterHftMessageManager;
        private TraceWriter _traceWriterHealthMonitorHFT;
        private Int64 _lastIdProcessed =0;
        private DumpClient.Dump _dump = null;
        private DumpEntity.DumpLineData _dumpLine = null;
        private DumpEntity.DumpErrorData _dumpError = null;

        //Constantes
        const string HFT_TRACE = "HftProcessor";
        const string HFT_FILENAME_TRACE = "HftMessageManagerLog";
        const string HFT_FILENAME_TRACE_HEALTHMONITOR = "HftMessageManagerHealthMonitorLog";
        const string HFT_FILENAME_DUMP = "MensagensProcessadas";
        #endregion 

        #region Construtor
        public STMMessageFlow()
        {
            try
            {
                HFTConfigurationManager.StartRefresh();
                _healthMonitor = HealthMonitorCollector.GetInstance();
                _hftProcessorStatus = HftProcessorShdms.GetSharedStorage();

                _dump = DumpClient.Dump.GetInstance();
                _dumpLine = new Sinacor.OMM.DumpEntity.DumpLineData();
                _dumpLine.FolderName = HFT_TRACE;
                _dumpLine.FileName = HFT_FILENAME_DUMP;

                _traceWriterHftMessageManager = Tracer.GetInstance(HFT_TRACE, HFT_FILENAME_TRACE);
                _traceWriterHealthMonitorHFT = Tracer.GetInstance(HFT_TRACE, HFT_FILENAME_TRACE_HEALTHMONITOR);

                _healthMonitor.AddHealthRequestListener(Collect, Sinacor.OMM.HealthMonitor.Entity.HealthType.HftProcessor);
                _TotalMessagesProcessed = 0;
                _TotalWaitOpenOrderTime = 0;
            }
            catch (Exception ex)
            {
                running = false;

                _traceWriterHftMessageManager.Trace(String.Format("Error in create Constructor HFT Message Manager", ex.ToString()), TraceType.Mandatory);
                _dumpError = new Sinacor.OMM.DumpEntity.DumpErrorData();
                _dumpError.ErrorDescription = "Error in create Constructor HFT Message Manager";
                _dumpError.ExceptionMessage = ex.Message;
                _dumpError.RecoveryProcedure = "Verify the configurations and restart proccess.";
                _dump.Send(_dumpError);

                this.Dispose();
                throw ex;
            }

        }
        #endregion

        #region HealthMonitor
        private object Collect()
        {
            //Message Processor
            _hftProcessorStatus.HFTProcessorDataInfo.NumberofHftProcess = HFTConfigurationManager.NumberOfHftProcess;
            _hftProcessorStatus.HFTProcessorDataInfo.MessageProcessor.TotalMessages = _TotalMessagesProcessed;
            if (_TotalWaitOpenOrderTime != 0)
            {
                _hftProcessorStatus.HFTProcessorDataInfo.MessageProcessor.WaitingOpenOrderAverageTime = (_hftProcessorStatus.HFTProcessorDataInfo.MessageProcessor.WaitingOpenOrderAverageTime + ((_TotalWaitOpenOrderTime) * (ConvertToMinute(_waitTime))) / 2);
            }
            else
            {
                _hftProcessorStatus.HFTProcessorDataInfo.MessageProcessor.WaitingOpenOrderAverageTime = 0;
            }
            _hftProcessorStatus.HFTProcessorDataInfo.MessageProcessor.LastMessageTime = _lastProcessTime;
            _hftProcessorStatus.HFTProcessorDataInfo.MessageProcessor.MessagesPerSecond = CalculateMessagesPerSecond();
            
            //DataBase
            _hftProcessorStatus.HFTProcessorDataInfo.Database.OperationAverageTime = CalculateDataBasePerSecond();
            if (dataBaseComunicator != null)
            {
                _hftProcessorStatus.HFTProcessorDataInfo.Database.SuccessfulTriesConnection = dataBaseComunicator.ConnectionTimes;
                _hftProcessorStatus.HFTProcessorDataInfo.Database.UnsuccessfulTriesConnection = dataBaseComunicator.ConnectionWithError;
            }
            else
            {
                _hftProcessorStatus.HFTProcessorDataInfo.Database.SuccessfulTriesConnection = 0;
                _hftProcessorStatus.HFTProcessorDataInfo.Database.UnsuccessfulTriesConnection = 0;

            }

            //Process
            Process currentProcess = Process.GetCurrentProcess();
            
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.PrivateMemory = currentProcess.PrivateMemorySize64;
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.LimitPrivateMemory = 104857600;
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.HandleCount = currentProcess.HandleCount;
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.LimitHandleCount = 900;
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.LimitThreadCount = 30;
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.ThreadCount = currentProcess.Threads.Count;
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.PrivilegedProcessorTime = currentProcess.PrivilegedProcessorTime.ToString();
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.InitializedDate = currentProcess.StartTime;
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.ThreadId = Thread.CurrentThread.ManagedThreadId.ToString();
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.ProcessId = currentProcess.Id.ToString();
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.MachineMacAddress = HFTConfigurationManager.HFTMessageManagerConfiguration.MacAddress;
            _hftProcessorStatus.HFTProcessorDataInfo.Msmq.LimitQueueBytesSize = Convert.ToInt64(HFTConfigurationManager.HFTMessageManagerConfiguration.MessageRepository.ConnectionInformation[Configuration.Repository.RepositoryPropertiesConstants.QueueBytesLimit]);
            _hftProcessorStatus.HFTProcessorDataInfo.Msmq.LimitQueuedMessages = Convert.ToInt64(HFTConfigurationManager.HFTMessageManagerConfiguration.MessageRepository.ConnectionInformation[Configuration.Repository.RepositoryPropertiesConstants.QueueMessageLimit]);
            _hftProcessorStatus.HFTProcessorDataInfo.Msmq.LimitQueueAcessible = true;
            
            //Machine
            if(String.IsNullOrEmpty(_hftProcessorStatus.HFTProcessorDataInfo.ProcessData.MachineName))
                _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.MachineName = Dns.GetHostName();
            if(String.IsNullOrEmpty(_hftProcessorStatus.HFTProcessorDataInfo.ProcessData.MachineIPAddress))
                _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.MachineIPAddress = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList[0].ToString();
            _hftProcessorStatus.HFTProcessorDataInfo.MessageProcessor.LimitWaitingOpenOrderAverageTime = 5;
            _hftProcessorStatus.HFTProcessorDataInfo.Database.LimitOperationAverageTime = 300;
            
            return _hftProcessorStatus;
        }

        private int CalculateMessagesPerSecond()
        {
            int seconds;
            int messagesReceivedPerSecond;

            // Calcula o número de segundos entre a última coleta e a coleta atual
            seconds = DateTime.Now.Subtract(_lastHealthStatusChecked).Seconds;

            if (seconds == 0)
                seconds = 1;

            if (_totalMessageSentPerInterval >= seconds)
                messagesReceivedPerSecond = _totalMessageSentPerInterval / seconds;
            else
                messagesReceivedPerSecond = _totalMessageSentPerInterval;

            // Zera o contador que será usado na próxima coleta
            // Esse contador é incrementado dentro do Run()
            // a cada mensagem recebida
            _totalMessageSentPerInterval = 0;

            // Define o horário dessa verificação, para ser usada na próxima chamada da função e calcular os segundos entre uma chamada e outra
            _lastHealthStatusChecked = DateTime.Now;

            return messagesReceivedPerSecond;
        }

        private int CalculateDataBasePerSecond()
        {
            int seconds;
            int messagesReceivedPerSecond;

            // Calcula o número de segundos entre a última coleta e a coleta atual
            seconds = DateTime.Now.Subtract(_lastHealthDBStatusChecked).Seconds;

            if (seconds == 0)
                seconds = 1;

            if (_totalDBPerInterval >= seconds)
                messagesReceivedPerSecond = _totalDBPerInterval / seconds;
            else
                messagesReceivedPerSecond = _totalDBPerInterval;

            // Zera o contador que será usado na próxima coleta
            // Esse contador é incrementado dentro do Run()
            // a cada mensagem recebida
            _totalDBPerInterval = 0;

            // Define o horário dessa verificação, para ser usada na próxima chamada da função e calcular os segundos entre uma chamada e outra
            _lastHealthDBStatusChecked = DateTime.Now;

            return messagesReceivedPerSecond;
        }

        private decimal ConvertToMinute(int number)
        {
            return number / 60000;
        }

        #endregion

        /// <summary>
        /// Start
        /// </summary>
        public void Start()
        {

            running = true;

            try
            {
                new OMM.Configuration.OrderBovespaSystem.OrderBovespaSystemConfigurationReader(HFTConfigurationManager.Authentication.CompanyId).GetOrderBovespaSystemInformation();
                _OrderDate = HFTConfigurationManager.OrderBovespaSystemInformation.SystemDate;
                StartLogic();
            }
            catch (Exception ex)
            {
                running = false;

                _traceWriterHftMessageManager.Trace(String.Format("Error trying to start HFT Message Manager Service. {0}", ex.ToString()), TraceType.Mandatory);
                _dumpError = new Sinacor.OMM.DumpEntity.DumpErrorData();
                _dumpError.ErrorDescription = "Error trying to start HFT Message Manager Service.";
                _dumpError.ExceptionMessage = ex.Message;
                _dumpError.RecoveryProcedure = "Verify the configurations and restart proccess.";
                _dump.Send(_dumpError);

                this.Dispose();
                throw ex;
            }
        }

        public void Dispose()
        {
            HFTConfigurationManager.StopRefresh();
            _traceWriterHftMessageManager.Trace("Trying to stop HFTMessageManager instance.", TraceType.Mandatory);
            
            running = false;
            
            if (_msmqReceiver != null)
                _msmqReceiver.Dispose();
            
            if (dataBaseComunicator != null)
                dataBaseComunicator.Dispose();
            
            if (_healthMonitor != null)
                _healthMonitor.Dispose();
            
            if (_dump != null)
                _dump.Dispose();

            if(_hftProcessorStatus != null)
                _hftProcessorStatus.Dispose();

            if (_hftLastIdFileManager != null)
                _hftLastIdFileManager.Dispose();

            _hftProcessorStatus = null;
            _hftLastIdFileManager = null;
            _msmqReceiver = null;
            _translator = null;
            _raHFTMessage = null;

            _traceWriterHftMessageManager.Trace("HFTMessageManager has been stopped.", TraceType.Mandatory);
            Tracer.Destroy();
        }

        private void StartLogic()
        {
            _traceWriterHftMessageManager.Trace("Initializing Oracle instance by companyId:" + HFTConfigurationManager.Authentication.CompanyId, TraceType.Mandatory);
            _hftProcessorStatus.HFTProcessorDataInfo.ProcessData.InitializedDate = Process.GetCurrentProcess().StartTime;
            OracleDatabase oracleDataBase = new OracleDatabase();
            oracleDataBase.CompanyId = HFTConfigurationManager.Authentication.CompanyId;
            dataBaseComunicator = new DataBaseCommunicator(oracleDataBase, "Oracle");
            _traceWriterHftMessageManager.Trace("Oracle instance initialized.", TraceType.Mandatory);

            _hftLastIdFileManager = new HFTLastIdFileManager(HFTConfigurationManager.HFTMessageManagerConfiguration.ControllerFilePath);
            _lastIdProcessed = _hftLastIdFileManager.ReadLastMsgId();
            _traceWriterHftMessageManager.Trace(string.Format("LastIdFileManager: {0}",_hftLastIdFileManager), TraceType.Mandatory);
            _traceWriterHftMessageManager.Trace(string.Format("LastIdProcessed: {0}", _lastIdProcessed), TraceType.Mandatory);

            string queuename = HFTConfigurationManager.HFTMessageManagerConfiguration.MessageRepository.ConnectionInformation[Configuration.Repository.RepositoryPropertiesConstants.ConnectionString];
            _traceWriterHftMessageManager.Trace(string.Format("Queue name: {0}", queuename));
            _msmqReceiver = new MsmqReceiver(queuename);
            _msmqReceiver.MessageReceived += new MsmqReceiver.MessageArrival(_msmqReceiver_MessageReceived);
            _msmqReceiver.OnHealthStatusChanged += new MsmqReceiver.HealthStatusChanged(_msmqReceiver_OnHealthStatusChanged);
            
            _hftProcessorStatus.HFTProcessorDataInfo.DistributionRules = new List<Sinacor.OMM.HealthMonitor.Entity.HftProcessor.DistributionRules>();
            HFTConfigurationManager.HFTMessageManagerConfiguration.DistributionRule.ForEach(delegate(DistributionRule item)
            {
                _hftProcessorStatus.HFTProcessorDataInfo.DistributionRules.Add(
                    new Sinacor.OMM.HealthMonitor.Entity.HftProcessor.DistributionRules()
                    {
                        ClientId = item.ClientId,
                        RangePort = (item.EndPort.Equals(0)) ? item.StartPort.ToString() : item.StartPort + " - " + item.EndPort
                    });
                _hftProcessorStatus.HFTProcessorDataInfo.LastUpdate = DateTime.Now;
            });

        }

        void _msmqReceiver_MessageReceived(System.Messaging.Message message, PSE.Framework.Messaging.MessageReceivedEventArgs e)
        {
            BaseMessage translatedMessage;
            try
            {
                if (HFTConfigurationManager.OrderBovespaSystemInformation.SystemDate != _OrderDate)
                {
                    if (_raHFTMessage == null)
                        _raHFTMessage = new ResourceAccess.HFTMessage(dataBaseComunicator);
                    _raHFTMessage.DbTransactionHFT = dataBaseComunicator.BeginTransaction();
                    _raHFTMessage.UpdateMessageIDProcessed(HFTConfigurationManager.HFTMessageManagerConfiguration.MacAddress);
                    _raHFTMessage.DbTransactionHFT.Commit();

                    _OrderDate = HFTConfigurationManager.OrderBovespaSystemInformation.SystemDate;

                    ResetCounter();
                }
                if (message.Label.Contains("OMMSystemMessage"))
                {
                    this.ResetCounter();
                    _hftLastIdFileManager.WriteLastMsgId(_lastIdProcessed.ToString());                    
                }
                else
                {
                    _traceWriterHftMessageManager.Trace(string.Format("Receiving message: {0} Label: {1}", (string)message.Body, message.Label), TraceType.Optional);
                    _translator = Translator.TranslatorFactory.GetTranslator(message.Label,
                                    message.Body.ToString(), Sinacor.OMM.Translator.Enum.ProtocolTypes.STM);
                    translatedMessage = _translator.TranslateToProcessMessage();

                    _traceWriterHftMessageManager.Trace(string.Format("SequencialID: {0} _lastIdProcessed: {1}", translatedMessage.SequentialID, _lastIdProcessed + 1), TraceType.Optional);
                    _traceWriterHftMessageManager.Trace(string.Format("ID: {0} LastMessageProcessed: {1}", translatedMessage.ID, HFTConfigurationManager.HFTMessageManagerConfiguration.LastMessageProcessed), TraceType.Optional);

                    if (translatedMessage.SequentialID == _lastIdProcessed + 1)
                    {
                        _lastIdProcessed++;
                        if (getNumber(translatedMessage.ID) > getNumber(HFTConfigurationManager.HFTMessageManagerConfiguration.LastMessageProcessed))
                        {
                            _traceWriterHftMessageManager.Trace(string.Format("Reading message: {0} Label: {1}", (string)message.Body, message.Label), TraceType.Optional);
                            InitializeMessageManager(translatedMessage);
                            _traceWriterHftMessageManager.Trace(string.Format("Read message: {0} Label: {1}", (string)message.Body, message.Label), TraceType.Optional);
                        }
                    }
                }

                e.Result = true;
            }
            catch (Exception ex)
            {
                if (_raHFTMessage.DbTransactionHFT != null)
                    _raHFTMessage.DbTransactionHFT.Rollback();
                _traceWriterHftMessageManager.Trace("[ReceiverMessage] Exception:" + ex.Message);
                e.Result = false;
            }            
        }

        #region MSMQ Receiver
        void _msmqReceiver_OnHealthStatusChanged(MsmqReceiver msmqReceiver)
        {
            //MSMQ
            _hftProcessorStatus.HFTProcessorDataInfo.Msmq.QueueAcessible = msmqReceiver.IsConnected;
            _hftProcessorStatus.HFTProcessorDataInfo.Msmq.QueuedMessages = msmqReceiver.QueuedMessages;
            _hftProcessorStatus.HFTProcessorDataInfo.Msmq.QueueBytesSize = msmqReceiver.QueueSizeBytes;

            //Connection
            _hftProcessorStatus.HFTProcessorDataInfo.TotalMsmqConnectionRetries = msmqReceiver.TotalMsmqConnectionTries;

            _traceWriterHealthMonitorHFT.Trace(string.Format("Event OnHealthStatusChanged - QueueAcessible: {0} QueuedMessages: {1} QueueBytesSize: {2} TotalMsmqConnectionRetries: {3}",msmqReceiver.IsConnected,msmqReceiver.QueuedMessages, msmqReceiver.QueueSizeBytes,msmqReceiver.TotalMsmqConnectionTries),TraceType.Optional);
        }

        private void ResetCounter()
        {
            _totalMessageSentPerInterval = 0;
            _totalDBPerInterval = 0;
            _TotalMessagesProcessed = 0;
            _TotalWaitOpenOrderTime = 0;
            _lastIdProcessed =0;
        }        

        private void InitializeMessageManager(Sinacor.OMM.MessageEntity.BaseMessage request)
        {
            bool processed = false;
            OrderParameter orderParameter = ConvertBaseMessageToProcess(request);
            ExecutionAttributes executionAttributes = ConvertBaseMessageToExecution(request);

            _raHFTMessage = new ResourceAccess.HFTMessage(dataBaseComunicator);

            while (!processed && 
                    running)
            {
                try
                {
                    _totalDBPerInterval++;
                    if (_raHFTMessage.CheckOrderExists(orderParameter))
                    {
                        _raHFTMessage.DbTransactionHFT = dataBaseComunicator.BeginTransaction();

                        _TotalWaitOpenOrderTime = 0;
                        _totalDBPerInterval++;
                        OrderBalanceResponse balance = _raHFTMessage.RetrieveOrderBalance(orderParameter);
                        _traceWriterHftMessageManager.Trace(string.Format("Order balance retrieved: Client: {0}  Operator: {1}  OrderSide: {2}  TradeCode{3} ", orderParameter.Client, orderParameter.Operator, orderParameter.OrderSide, orderParameter.TradeCode), TraceType.Optional);
                        OrderAdditionalParameter orderAdditional = ConvertOrderParameterToOrderAdditional(balance);
                        MatchExecutionParameter matchExecution = ConvertOrderParameterToMatchExecution(balance);
                        //Execute the sum of the additional value in the balance of the order
                        orderAdditional.AdditionalValue = executionAttributes.Balance - balance.Balance;

                        _totalDBPerInterval++;

                        if (orderAdditional.AdditionalValue > 0)
                        _raHFTMessage.OrderAdditional(orderAdditional);

                        executionAttributes.OrderSequencialNumber = orderAdditional.OrderSequencialNumber;
                        executionAttributes.OrderSubSequencialNumber = orderAdditional.OrderSubSequencialNumber;
                        executionAttributes.OrderDate = orderAdditional.OrderDate;
                        _traceWriterHftMessageManager.Trace(string.Format("Order additional: OrderSequencialNumber: {0}  OrderSubSequencialNumber: {1}  OrderDate: {2}  ", executionAttributes.OrderSequencialNumber, executionAttributes.OrderSubSequencialNumber, executionAttributes.OrderDate), TraceType.Optional);

                        _totalDBPerInterval++;
                        ExecutionInformation executionInformation = _raHFTMessage.RetrieveExecutionInformation(orderAdditional);
                        executionAttributes.HourOrder = executionInformation.HourOrder;
                        executionAttributes.MarketCode = executionInformation.MarketCode;
                        executionAttributes.OrderType = executionInformation.OrderType;
                        executionAttributes.OperationalDate = HFTConfigurationManager.OrderBovespaSystemInformation.SystemDate;
                        _traceWriterHftMessageManager.Trace(string.Format("Execution information retrieved: HourOrder: {0}  MarketCode: {1}  OrderType: {2}  OperationalDate:{3} ", executionAttributes.HourOrder, executionAttributes.MarketCode, executionAttributes.OrderType, executionAttributes.OperationalDate), TraceType.Optional);

                        _totalDBPerInterval++;
                        matchExecution.sequencialCode = _raHFTMessage.IncludeExecution(executionAttributes);
                        _traceWriterHftMessageManager.Trace("Execution included.", TraceType.Optional);

                        _totalDBPerInterval++;
                        _raHFTMessage.IncludeMatchExecutionQueue(matchExecution);
                        _traceWriterHftMessageManager.Trace("Match Execution Queue included.", TraceType.Optional);

                        _totalDBPerInterval++;
                        _raHFTMessage.UpdateMessageIDProcessed(request.ID, HFTConfigurationManager.HFTMessageManagerConfiguration.MacAddress);
                        _traceWriterHftMessageManager.Trace(string.Format("Message ID {0} processed updated.", request.ID), TraceType.Optional);
                        HFTConfigurationManager.HFTMessageManagerConfiguration.LastMessageProcessed = request.ID;

                        processed = true;
                        _totalMessageSentPerInterval++;
                        _TotalMessagesProcessed++;
                        _lastProcessTime = DateTime.Now;

                        _raHFTMessage.DbTransactionHFT.Commit();

                        _dumpLine.DataToDump = string.Concat(request.ID, " ", request.Original);
                        _dump.Send(_dumpLine);

                        _hftLastIdFileManager.WriteLastMsgId(_lastIdProcessed.ToString());
                    }
                    else
                    {
                        _traceWriterHftMessageManager.Trace("Waiting to check if order was created.", TraceType.Mandatory);
                        _traceWriterHftMessageManager.Trace("Client: " + orderParameter.Client + " Operator: " + orderParameter.Operator + " OrderSide: " + orderParameter.OrderSide + " TradeCode: " + orderParameter.TradeCode, TraceType.Mandatory);

                        Sleeper.Sleep(_waitTime, IsRunning);//Wait for 1 minute to check if the order was created
                        _TotalWaitOpenOrderTime++;
                        processed = false;
                    }
                }
                catch (Exception ex)
                {
                    if (_raHFTMessage.DbTransactionHFT != null)
                        _raHFTMessage.DbTransactionHFT.Rollback();

                    _traceWriterHftMessageManager.Trace(String.Format("Error trying to process message {0}. {1}",request.ID,ex.ToString()), TraceType.Mandatory);
                    _traceWriterHftMessageManager.Trace("Client: " + orderParameter.Client + " Operator: " + orderParameter.Operator + " OrderSide: " + orderParameter.OrderSide + " TradeCode: " + orderParameter.TradeCode, TraceType.Mandatory);

                    Sleeper.Sleep(_waitTime, IsRunning);//Wait for 1 minute to check if the order was created
                    _TotalWaitOpenOrderTime++;
                    processed = false;
                }
            }
        }

        private bool IsRunning()
        {
            return running;
        }

        private ProcessEntity.Parameter.OrderParameter ConvertBaseMessageToProcess(Sinacor.OMM.MessageEntity.BaseMessage request)
        {
            MessageEntity.STM.Message0103 message0103 = null;
            MessageEntity.STM.Message0105 message0105 = null;
            ProcessEntity.Parameter.OrderParameter parameter = new Sinacor.OMM.HFTMessageManager.ProcessEntity.Parameter.OrderParameter();

            if (request is MessageEntity.STM.Message0103)
            {
                message0103 = (MessageEntity.STM.Message0103)request;
                parameter.OrderSide = message0103.NaturezaOperacao == Sinacor.OMM.MessageEntity.Enum.NaturezaOperacao.Compra ? "C" : "V";
                parameter.TradeCode = message0103.Stock;
                parameter.Client = message0103.Client;
                parameter.Operator = message0103.Operator;
                parameter.SystemDate = message0103.SystemDate;
            }

            if (request is MessageEntity.STM.Message0105)
            {
                message0105 = (MessageEntity.STM.Message0105)request;
                parameter.OrderSide = message0105.NaturezaOperacao == Sinacor.OMM.MessageEntity.Enum.NaturezaOperacao.Compra ? "C" : "V";
                parameter.TradeCode = message0105.Stock;
                parameter.Client = message0105.Client;
                parameter.Operator = message0105.Operator;
                parameter.SystemDate = message0105.SystemDate;
            }
            return parameter;
        }

        #endregion



        private ProcessEntity.Parameter.OrderAdditionalParameter ConvertOrderParameterToOrderAdditional(Sinacor.OMM.HFTMessageManager.ProcessEntity.OrderBalanceResponse request)
        {
            return new Sinacor.OMM.HFTMessageManager.ProcessEntity.Parameter.OrderAdditionalParameter() { OrderDate = request.OrderDate, OrderSequencialNumber = request.OrderSequencialNumber, OrderSubSequencialNumber = request.OrderSubSequencialNumber };
        }

        private ProcessEntity.Parameter.MatchExecutionParameter ConvertOrderParameterToMatchExecution(Sinacor.OMM.HFTMessageManager.ProcessEntity.OrderBalanceResponse request)
        {
            return new Sinacor.OMM.HFTMessageManager.ProcessEntity.Parameter.MatchExecutionParameter() { OrderDate = request.OrderDate, OrderSequencialNumber = request.OrderSequencialNumber, OrderSubSequencialNumber = request.OrderSubSequencialNumber };
        }

        private ProcessEntity.ExecutionAttributes ConvertBaseMessageToExecution(Sinacor.OMM.MessageEntity.BaseMessage request)
        {
            Sinacor.OMM.HFTMessageManager.ProcessEntity.ExecutionAttributes response = new Sinacor.OMM.HFTMessageManager.ProcessEntity.ExecutionAttributes();
            if (request is MessageEntity.STM.Message0103)
            {
                MessageEntity.STM.Message0103 item = (MessageEntity.STM.Message0103)request;
                response.Counterparty = item.Counterparty;
                response.FunctionCode = item.FunctionCode;
                response.sequencialCode = item.SequentialID;
                response.MegaOrder = item.MegaOrder;
                response.Balance = Decimal.Parse(item.OrderQuantity);
                response.OrderSide = item.OrderSide;
                response.Price = item.Price;
                response.Security = item.Security;
                response.SystemDate = item.SystemDate;

            }
            if (request is MessageEntity.STM.Message0105)
            {
                MessageEntity.STM.Message0105 item = (MessageEntity.STM.Message0105)request;
                response.Counterparty = item.Counterparty;
                response.FunctionCode = item.FunctionCode;
                response.sequencialCode = item.SequentialID;
                response.MegaOrder = item.MegaOrder;
                response.Balance = Decimal.Parse(item.OrderQuantity);
                response.OrderSide = item.OrderSide;
                response.Price = item.Price;
                response.Security = item.Security;
                response.SystemDate = item.SystemDate;
            }
            return response;
        }

        private Decimal getNumber(string msgId)
        {
            return (msgId == null || msgId.Equals("0")) ? 0 : Convert.ToDecimal(string.Concat(msgId.Substring(0, 8), Char.ConvertToUtf32(msgId.ToUpper(), 8), msgId.Substring(9)));
        }
    }
}
